package com.cndw.kungfu.model.scene;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;

import org.springframework.stereotype.Component;

import com.cndw.kungfu.domain.Pendant;
import com.cndw.kungfu.domain.Player;
import com.cndw.kungfu.domain.Scene;
import com.cndw.kungfu.event.model.PendantHandler;
import com.cndw.kungfu.ext.NumberProcesser;
import com.cndw.kungfu.model.Context;
import com.cndw.kungfu.vo.EventNotice;
import com.cndw.kungfu.vo.PendantVO;

/**
 * 场景挂件控制器
 * 
 * @author fantadust [9677889@qq.com]
 * @date 2011-9-23 下午5:49:32
 */
@Component
public class PendantManager {

	private static Map<Integer, List<PendantVO>> dataMap = new ConcurrentHashMap<Integer, List<PendantVO>>();

	private static int signId = 0;

	private static Map<Integer, Set<Integer>> xyDataMap = new ConcurrentHashMap<Integer, Set<Integer>>();

	private static Map<Integer, PendantVO> pendantVOMap = new ConcurrentHashMap<Integer, PendantVO>();

	private static synchronized int makeUniqueId() {
		signId++;
		signId = signId >= Integer.MAX_VALUE ? 1 : signId;
		return signId;
	}

	public List<PendantVO> getPendants(int sceneId) {
		if (dataMap.containsKey(sceneId) == false) {
			List<Pendant> pendants = Context.getCacheCenter().getPendantBySceneId(sceneId);
			if (pendants == null || !PendantHandler.isOpen(sceneId)) {
				return null;
			}
			initPendantsByScene(sceneId);
		}
		return dataMap.get(sceneId);
	}



	private static synchronized void initPendantsByScene(int sceneId) {
		if (dataMap.containsKey(sceneId)) {
			return ;
		}
		List<Pendant> pendants = Context.getCacheCenter().getPendantBySceneId(sceneId);
		if (pendants == null) {
			return ;
		}

		for (Pendant e : pendants) {
			int refreshNum = e.getRefreshNum();
			refreshNum = refreshNum <= 0 ? 1 : refreshNum;

			while (refreshNum > 0) {
				refreshNum--;
				initOnePendant(e);
			}

		}
	}

	private static  PendantVO initOnePendant(Pendant e) {
		int x = e.getX();
		int y = e.getY();
		int sceneId = e.getSceneId();
		int uniqueId = makeUniqueId();
		if (e.getRandX() > 0 || e.getRandY() > 0) {
			int tryTimes = 20;
			do {
				tryTimes--;
				x = e.getX() + NumberProcesser.mtRand(e.getRandX());
				y = e.getY() + NumberProcesser.mtRand(e.getRandY());
			} while (isUniqueXY(sceneId, x, y) == false && tryTimes > 0);
		}
		PendantVO pendantVO = new PendantVO(uniqueId, x, y, e);

		if (dataMap.containsKey(sceneId) == false) {
			dataMap.put(sceneId, new ArrayList<PendantVO>());
		}
		dataMap.get(sceneId).add(pendantVO);
		pendantVOMap.put(pendantVO.getUniqueId(), pendantVO);

		return pendantVO;
	}
	
	/**
	 * 检查坐标是否重复
	 * 
	 * @param sceneId
	 * @param x
	 * @param y
	 * @return
	 */
	private static boolean isUniqueXY(int sceneId, int x, int y) {
		int hashXY = x * 10000 + y;
		if (xyDataMap.containsKey(sceneId) == false) {
			Set<Integer> hashXYs = new ConcurrentSkipListSet<Integer>();
			hashXYs.add(hashXY);
			xyDataMap.put(sceneId, hashXYs);
			return true;
		} else {
			Set<Integer> hashXYs = xyDataMap.get(sceneId);
			if (hashXYs.contains(hashXY) == false) {
				hashXYs.add(hashXY);
				return true;
			}
		}

		return false;
	}
	

	public PendantVO getPendantVO(int uniqueId) {
		return pendantVOMap.get(uniqueId);
	}

	public Pendant getpPendant(int id) {
		return Context.getSceneServer().getpPendant(id);
	}

	/**
	 * 刷新某个资源点
	 * 
	 * @param pendantVO
	 */
	public void refreshPendantVO(final Player player, final PendantVO pendantVO) {
		final Pendant pendant = Context.getSceneServer().getpPendant(pendantVO.getId());
		if (pendant.getTypeRefresh() == Pendant.refreshTypeShareD && pendant.getIntervalTime() > 0) {
			final Scene scene = Context.getSceneServer().getSceneById(pendant.getSceneId());

			pendantVOMap.remove(pendantVO.getUniqueId());
			if (dataMap.containsKey(pendant.getSceneId())) {
				dataMap.get(pendant.getSceneId()).remove(pendantVO);
			}

			EventNotice eventNotice = new EventNotice("pendant", "remove");
			eventNotice.put("eventId", pendantVO.getUniqueId());
			eventNotice.broadcastAllScene(scene.getId());

			//scene.broadcast(player, eventNotice, ConstantsRadio.eventNotice);
			
			if (!PendantHandler.isOpen(scene.getId())) {
				return ;
			}

			Runnable r = new Runnable() {
				@Override
				public void run() {
					if (!PendantHandler.isOpen(scene.getId())) {
						return ;
					}

					PendantVO pendantVONew = initOnePendant(pendant);
					EventNotice eventNotice = new EventNotice("pendant", "display");
					eventNotice.put("eventData", pendantVONew);
					eventNotice.broadcastAllScene(scene.getId());
					//scene.broadcast(player, eventNotice, ConstantsRadio.eventNotice);
				}
			};
			Context.getTimerServer().scheduleSeconds(r, pendant.getIntervalTime());
		}
	}

	public static synchronized void pendantTask(int sceneId,boolean add) {
		if (add) {
			dataMap.remove(sceneId);
			initPendantsByScene(sceneId);
			List<PendantVO> pendants = dataMap.get(sceneId);
			if (pendants != null ) {
				for (PendantVO pendantVO : pendants) {
					EventNotice eventNotice = new EventNotice("pendant", "display");
					eventNotice.put("eventData", pendantVO);
					eventNotice.broadcastAllScene(sceneId);
				}
			}
		}else {
			dataMap.remove(sceneId);
		}
		
	}

}
